﻿using Microsoft.AspNetCore.Mvc;
using wwl.Contract.Dtos.Common;
using wwl.Contract.Enums;

namespace wwl.WebApi.Controllers.Common
{
  /// <summary>
  /// 控制器抽象基类，为所有业务控制器提供通用能力
  /// 核心价值：
  /// 1. 统一接口响应格式（对接ApiResponse和CustomErrorCode）
  /// 2. 封装通用逻辑（身份获取、模型验证、分页处理）
  /// 3. 规范业务控制器实现标准，减少重复代码
  /// 用法：业务控制器通过继承使用（如 TenantController : BaseController）
  /// </summary>
  [ApiController] // 子类继承后自动启用：
                  // - 自动模型验证（基于数据注解）
                  // - 自动参数源推断（[FromBody]等）
                  // - 需配合全局配置禁用默认400响应（见扩展建议）
  public abstract class BaseController : ControllerBase
  {
    #region 身份获取方法
    /// <summary>
    /// 获取当前登录用户唯一标识（ID）
    /// 应用场景：创建/修改数据时记录操作人（CreatedBy/UpdatedBy）
    /// </summary>
    /// <returns>用户ID字符串（未登录返回"anonymous"）</returns>
    /// <remarks>
    /// 实际项目需替换为真实身份解析逻辑，示例：
    /// return User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "anonymous";
    /// 依赖：需在认证中间件中正确设置Claim（如JWT验证后）
    /// </remarks>
    protected string GetCurrentUserId()
    {
      // 占位实现：实际项目请从认证上下文解析
      return "system";
    }
    #endregion

    #region 统一响应方法（核心功能）
    /// <summary>
    /// 成功响应（带业务数据）
    /// 适用场景：查询单条数据、创建数据等需返回结果的操作
    /// </summary>
    /// <typeparam name="T">业务数据类型（如TenantDto、List&lt;UserDto&gt;）</typeparam>
    /// <param name="data">需返回的业务数据（可为null）</param>
    /// <param name="message">自定义成功消息（默认"操作成功"）</param>
    /// <returns>HTTP 200 + 标准化ApiResponse&lt;T&gt;格式</returns>
    /// <example>
    /// 返回示例：
    /// {
    ///   "code": 0,
    ///   "message": "查询成功",
    ///   "data": { "id": "1", "name": "租户A" },
    ///   "timestamp": 1710000000000
    /// }
    /// </example>
    protected IActionResult SuccessResult<T>(T? data, string message = "操作成功")
    {
      return Ok(ApiResponse<T>.Success(data, message));
    }

    /// <summary>
    /// 成功响应（无业务数据）
    /// 适用场景：删除、启用/禁用等只需确认结果的操作
    /// </summary>
    /// <param name="message">自定义成功消息（默认"操作成功"）</param>
    /// <returns>HTTP 200 + 标准化ApiResponse格式（data为null）</returns>
    protected IActionResult SuccessResult(string message = "操作成功")
    {
      return Ok(ApiResponse.Success(message));
    }

    /// <summary>
    /// 失败响应（带错误码，无业务数据）
    /// 适用场景：所有业务异常（如资源不存在、权限不足）
    /// </summary>
    /// <param name="errorCode">错误码（来自CustomErrorCode枚举，确保标准化）</param>
    /// <param name="message">错误详情（需明确原因，如"租户编码已存在"）</param>
    /// <returns>HTTP 200 + 标准化ApiResponse格式（code为错误码）</returns>
    /// <remarks>
    /// 错误消息规范：
    /// - 参数错误：说明"哪个参数+问题"（如"页码必须≥1"）
    /// - 业务错误：说明"原因+解决方案"（如"租户已冻结，请先解冻"）
    /// - 系统错误：避免暴露技术细节（如"系统异常，请联系管理员"）
    /// </remarks>
    protected IActionResult FailResult(CustomErrorCode errorCode, string message)
    {
      return Ok(ApiResponse.Fail((int)errorCode, message));
    }

    /// <summary>
    /// 失败响应（带错误码和泛型数据）
    /// 适用场景：需返回部分数据的失败场景（如表单验证失败返回已填值）
    /// </summary>
    /// <typeparam name="T">附加数据类型</typeparam>
    /// <param name="errorCode">错误码（来自CustomErrorCode枚举）</param>
    /// <param name="message">错误详情</param>
    /// <param name="data">附加数据（可选）</param>
    /// <returns>HTTP 200 + 标准化ApiResponse&lt;T&gt;格式</returns>
    protected IActionResult FailResult<T>(CustomErrorCode errorCode, string message, T? data = default)
    {
      return Ok(ApiResponse<T>.Fail((int)errorCode, message));
    }

    /// <summary>
    /// 分页查询专用响应
    /// 适用场景：所有分页查询接口（自动包装PagedResult&lt;T&gt;）
    /// </summary>
    /// <typeparam name="T">分页数据项类型</typeparam>
    /// <param name="pagedResult">分页查询结果（含Items、TotalCount等）</param>
    /// <param name="message">查询成功消息（默认"查询成功"）</param>
    /// <returns>HTTP 200 + 包含分页信息的ApiResponse</returns>
    protected IActionResult PagedResult<T>(PagedResult<T> pagedResult, string message = "查询成功")
    {
      return SuccessResult(pagedResult, message);
    }
    #endregion

    #region 模型验证方法
    /// <summary>
    /// 校验前端传入参数的合法性（基于数据注解）
    /// 适用场景：所有接收参数的接口（必须在方法开头调用）
    /// </summary>
    /// <returns>
    /// true：验证通过，可继续执行业务逻辑
    /// false：验证失败，已自动返回错误响应（无需后续处理）
    /// </returns>
    /// <example>
    /// 使用示例：
    /// <code>
    /// [HttpPost]
    /// public async Task&lt;IActionResult&gt; Create(CreateDto dto)
    /// {
    ///     if (!CheckModelState()) return new EmptyResult();
    ///     // 业务逻辑...
    /// }
    /// </code>
    /// </example>
    protected bool CheckModelState()
    {
      if (ModelState.IsValid) return true;

      // 聚合所有验证错误信息
      var errorMessages = ModelState.Values
          .SelectMany(v => v.Errors)
          .Select(e => e.ErrorMessage)
          .ToList();

      var message = errorMessages.Any()
          ? string.Join("；", errorMessages)
          : "参数验证失败，请检查输入";

      // 自动返回参数错误响应（默认映射Param_Required）
      //Response.OnStarting 的作用:
      //1、由于 CheckModelState 是 bool 返回值的方法，无法直接返回 IActionResult，通过 Response.OnStarting 可在响应发送前注入错误响应，实现 “自动返回” 效果。
      //2、回调中调用 ExecuteResultAsync，将 FailResult 生成的 IActionResult（如 Ok(ApiResponse.Fail(...))）写入响应，等同于接口手动返回该结果。
      Response.OnStarting(async () =>
      {
        var result = FailResult(CustomErrorCode.Param_Required, message);
        await result.ExecuteResultAsync(ControllerContext);
      });
      return false;
    }
    #endregion

    #region 扩展建议（可按需添加）
    // <summary>
    // 【扩展示例】权限校验方法
    // 作用：统一校验当前用户是否拥有指定权限
    // </summary>
    // <param name="permissionCode">权限编码（如"tenant:delete"）</param>
    // <returns>是否有权限</returns>
    //protected async Task<bool> CheckPermissionAsync(string permissionCode)
    // {
    //     var userId = GetCurrentUserId();
    //     return await _permissionService.VerifyAsync(userId, permissionCode);
    // }

    // <summary>
    // 【扩展示例】操作日志记录
    // 作用：统一记录接口操作日志（谁、何时、做了什么）
    // </summary>
    // <param name="operation">操作描述（如"删除租户"）</param>
    // <param name="targetId">操作目标ID（如租户ID）</param>
    // protected void LogOperation(string operation, string targetId)
    // {
    //     _logger.LogInformation("{UserId} {Operation} {TargetId} at {Time}",
    //         GetCurrentUserId(), operation, targetId, DateTime.Now);
    // }
    #endregion
  }
}